/**
 * Copyright 2011 The Apache Software Foundation
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package enterprise.web_jpa_war.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * The sevelet class to insert Person into database
 */
public class CreatePersonServlet extends AbstractServlet {
    
    private static final String SQL_QUERY_CURRENT_PERSON_ID = "SELECT CURRVAL('PERSON_ID_SEQ') FROM DUAL";  
	
	private static final String SQL_INSERT_PERSON = 
		"INSERT INTO PERSON(ID, LAST_NAME, FIRST_NAME, ACCOUNT_NAME, PASSWORD) " +
		"VALUES(NEXTVAL('PERSON_ID_SEQ'), ?, ?, UPPER(?), ?)";

	/** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws IOException 
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    	//Get the data from user's form
        String firstName 	= request.getParameter("firstName");
        String lastName 	= request.getParameter("lastName");
        String accountName 	= request.getParameter("accountName");
        String[] roleNames 	= request.getParameterValues("roleName");
        String password 	= request.getParameter("password");
        Long newPersonId = null;
    	List<Long> roleIds = null;
    	
        Connection connection = null;
        PreparedStatement statement = null;
        try {
			connection = this.getConnection();
			//HEAD: transaction boundary
	        connection.setAutoCommit(false);
	        //1. insert person
	    	insertPerson(firstName, lastName, accountName,
					password, connection);
	    	
	    	//2. get newly inserted person's id
	    	newPersonId = getNewPersonId(connection);
	    	
	    	//3. get corresponding roles' id
	    	roleIds = getRoleIds(connection, roleNames);
	    	
	    	//4. insert person_roles relationship
	    	insertPersonRolesRelationship(accountName, roleNames,
					newPersonId, roleIds, connection);
    	
        } catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException("insert person failed", e);
		} finally {
			closeStatement(statement);
			//TAIL: transaction boundary
			closeConnection(connection);
		}
    	
    	request.getRequestDispatcher("/person/ListPerson").forward(request, response);
    	
    }

	private void insertPerson(String firstName, String lastName,
			String accountName, String password, Connection connection)
			throws SQLException {
		PreparedStatement statement = null;
		
		try {
			statement = connection.prepareStatement(SQL_INSERT_PERSON);
			statement.setString(1, lastName);
			statement.setString(2, firstName);
			statement.setString(3, accountName);
			statement.setString(4, password);
			statement.execute();
		} finally {
			closeStatement(statement);
		}
	}
	
	private Long getNewPersonId(Connection connection) throws SQLException{
		Long newPersonId = null;
		PreparedStatement statement = null;
		ResultSet resultSet = null;
		
		try {
			statement = connection.prepareStatement(SQL_QUERY_CURRENT_PERSON_ID);
	    	resultSet = statement.executeQuery();
	    	if(resultSet.next()) 
	    		newPersonId = resultSet.getLong(1);
		} finally {
			closeStatement(statement);
		}
    	return newPersonId;
	}
	
	// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
    
    /** Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
}
